package org.example.writebitfile;

/**
 * {@code @projectName} bitmap17
 * {@code @Author} huzhengyang
 * {@code @Create} 2024/4/22 23:06
 */
import org.example.util.*;
import org.roaringbitmap.RoaringBitmap;
import org.roaringbitmap.longlong.Roaring64Bitmap;

import java.awt.geom.GeneralPath;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class SerializeToDiskExample {


    public static void main(String[] args) throws IOException {
        if (args.length > 0) {
            String file1 = args[0];
            String file2 = args[1];
            String diff1 = args[2];
            String diff2 = args[3];
            String diff3 = args[4];

            long d1 = Long.parseLong(diff1);
            long d2 = Long.parseLong(diff2);
            long d3 = Long.parseLong(diff3);

            CountDownLatch latch = new CountDownLatch(2);

            Thread t1 = new Thread(() -> {
                try {
                    generateFile(file1, null);
                    latch.countDown();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });

            Thread t2 = new Thread(() -> {
                try {
                    generateFile(file2, Arrays.asList(d1, d2, d3));
                    latch.countDown();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });

            t1.start();
            t2.start();

            try {
                latch.await();
            } catch (InterruptedException e) {
                System.err.println("InterruptedException: " + e.getMessage());
            } catch (Exception e) {
                System.err.println("Exception: " + e.getMessage());
            }


        } else {
            System.err.println("must input tow file full path, and diff row number");
        }
    }

    public static void generateFile(String fileFullPath, List<Long> collectionOfDiff) throws IOException {
        Roaring64Bitmap rb = new Roaring64Bitmap();

        if (collectionOfDiff != null && !collectionOfDiff.isEmpty()) {
            for (long k = 0; k < 20000000; k++) {
                String datum = "aaaaa" + k;
            if (collectionOfDiff.contains(k)) {
                datum = "bbbbb" + k;
            }
                //long crcId = CRC32Util.crc32Id(datum);
                //long crcId = CRC64Util.crc64Long(datum);
                //long crcId = GenerateUtil.getHash(datum);
                // long crcId = CRC64.getId(datum);
                long crcId = MurmurHashUtil.getLongFromString(datum);
                //System.out.println(crcId);
                rb.add(crcId);
            }
        } else {
            for (long k = 0; k < 20000000; k++) {
                String datum = "aaaaa" + k;
//            if (k == 199999 || k == 3500099 || k == 18110098) {
//                datum = "bbbbb" + k;
//            }
            /*if (k == 5) {
                datum = "bbbbb" + k;
            }*/
            /*if (k == 1) {
                datum = "bbbbb" + k;
            }*/
                //long crcId = CRC32Util.crc32Id(datum);
                //long crcId = CRC64Util.crc64Long(datum);
                //long crcId = GenerateUtil.getHash(datum);
                //long crcId = CRC64.getId(datum);
                long crcId = MurmurHashUtil.getLongFromString(datum);
                //System.out.println(crcId);
                rb.add(crcId);
            }
        }


        //System.out.println(rb);
//        for (long k = 100000000; k < 300000000; k= k + 2) {
//            rb.add(k);
//        }
        //long start = System.currentTimeMillis();
        //String file1 = "D:\\iProject\\javapath\\bitmap17\\data\\big\\bitmapwithoutruns.bin";
//        String file1 = "D:\\iProject\\javapath\\bitmap17\\data\\small\\bitmapwithoutruns1.bin";
        try (DataOutputStream out = new DataOutputStream(new FileOutputStream(fileFullPath))) {
            rb.serialize(out);
        }
        /*System.out.println("序列化耗时：" + getCost(start) + "秒");
        start = System.currentTimeMillis();
        rb.runOptimize();
        System.out.println("优化压缩耗时：" + getCost(start) + "秒");*/
        //start = System.currentTimeMillis();
//        String file2 = "D:\\工作\\bitmapwithruns.bin";
//        try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file2))) {
//            rb.serialize(out);
//        }
//        System.out.println("优化后，序列化耗间：" + getCost(start) + "秒");
        // verify
        /*Roaring64Bitmap rbtest = new Roaring64Bitmap();
        start = System.currentTimeMillis();
        try (DataInputStream in = new DataInputStream(new FileInputStream(fileFullPath))) {
            rbtest.deserialize(in);
        }
        System.out.println("verify耗时：" + getCost(start) + "秒");
        System.out.println(rbtest.getLongCardinality());*/
        //System.out.println(rbtest);
//        System.out.println("读取文件，反序列化耗间：" + getCost(start) + "秒");
//        start = System.currentTimeMillis();
//        if(!rbtest.equals(rb)) throw new RuntimeException("bug!");
//        try (DataInputStream in = new DataInputStream(new FileInputStream(file2))) {
//            rbtest.deserialize(in);
//        }
//        System.out.println("优化后，读取文件，反序列化耗间：" + getCost(start) + "秒");
//        if(!rbtest.equals(rb)) throw new RuntimeException("bug!");
//        System.out.println("Serialized bitmaps to "+file1+" and "+file2);
    }


    public static long getCost(long start) {
        return (System.currentTimeMillis() - start) / 1000;
    }
}